package com.fan.analysis.module.analysis.group.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fan.analysis.common.domain.ResponseDTO;
import com.fan.analysis.module.analysis.group.constant.GroupResponseCodeConst;
import com.fan.analysis.module.analysis.group.dao.GroupInfoDao;
import com.fan.analysis.module.analysis.group.dao.RegionDao;
import com.fan.analysis.module.analysis.group.dao.UserGroupDao;
import com.fan.analysis.module.analysis.group.dao.UserRelationDao;
import com.fan.analysis.module.analysis.group.domain.bo.FrequentContactBo;
import com.fan.analysis.module.analysis.group.domain.bo.LinkBo;
import com.fan.analysis.module.analysis.group.domain.bo.NodeBo;
import com.fan.analysis.module.analysis.group.domain.bo.NodesAndLinksBo;
import com.fan.analysis.module.analysis.group.domain.entity.GroupInfoEntity;
import com.fan.analysis.module.analysis.group.domain.entity.RegionEntity;
import com.fan.analysis.module.analysis.group.domain.entity.UserInfoEntity;
import com.fan.analysis.module.analysis.group.domain.entity.UserRelationEntity;
import com.fan.analysis.module.analysis.group.domain.vo.GroupInfoVo;
import com.fan.analysis.module.analysis.group.domain.vo.GroupVo;
import com.fan.analysis.module.analysis.group.domain.vo.KeyPersonInfoVo;
import com.fan.analysis.module.analysis.group.domain.vo.UserGroupVo;
import com.fan.analysis.module.analysis.group.service.UserGroupService;
import com.fan.analysis.util.CollectionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * 用户群体识别服务
 *
 * @author fan
 * @date 2021/09/23 20:59
 **/
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class UserGroupServiceImpl implements UserGroupService {

    private final UserGroupDao userGroupDao;
    private final GroupInfoDao groupInfoDao;
    private final UserRelationDao userRelationDao;
    private final RegionDao regionDao;

    @Autowired
    public UserGroupServiceImpl(UserGroupDao userGroupDao, GroupInfoDao groupInfoDao, UserRelationDao userRelationDao, RegionDao regionDao) {
        this.userGroupDao = userGroupDao;
        this.groupInfoDao = groupInfoDao;
        this.userRelationDao = userRelationDao;
        this.regionDao = regionDao;
    }

    @Override
    public ResponseDTO<UserGroupVo> getNodeLinkGroupInfo(String phoneNum) {

        UserGroupVo userGroupVo = new UserGroupVo();

        List<NodeBo> nodes = new ArrayList<>();
        List<LinkBo> links = new ArrayList<>();
        NodesAndLinksBo nodesAndLinksBo = new NodesAndLinksBo();

        // -------------- 1、查找是否有此人，无此人直接返回 ------------------------
        UserInfoEntity userInfoEntity = userGroupDao.selectOne(new QueryWrapper<UserInfoEntity>().eq("phone_num", phoneNum));
        System.out.println(userInfoEntity);
        if (null == userInfoEntity) {
            userGroupVo.setStatus(0);
            return ResponseDTO.wrap(GroupResponseCodeConst.PHONE_NOT_EXISTS);
        }
        // -------------- 2、有此人，将此人的信息保存为一个结点 ---------------------
        userGroupVo.setThisUser(userInfoEntity);
        NodeBo thisNode = NodeBo.builder().name(userInfoEntity.getPhoneNum()).value(String.valueOf(userInfoEntity.getInfluence()))
                .category(0).attr(userInfoEntity).symbol("image://../images/user.jpg").symbolSize(new Integer[]{60, 80}).build();
        nodes.add(thisNode);


        // -------------- 3、解析出此人所属于的群体ids        ---------------------
        if (userInfoEntity.getFriendsGroupId() == null) {
            userInfoEntity.setFriendsGroupId("");
        }
        if (userInfoEntity.getWorkGroupId() == null) {
            userInfoEntity.setWorkGroupId("");
        }
        if (userInfoEntity.getFamilyGroupId() == null) {
            userInfoEntity.setFamilyGroupId("");
        }
        // 群体id
        String[] friendsGroupId = userInfoEntity.getFriendsGroupId().split(",");
        ArrayList<String> groupIds = new ArrayList<>(Arrays.asList(friendsGroupId));
        String[] workGroupId = userInfoEntity.getWorkGroupId().split(",");
        groupIds.addAll(Arrays.asList(workGroupId));
        String[] familyGroupId = userInfoEntity.getFamilyGroupId().split(",");
        groupIds.addAll(Arrays.asList(familyGroupId));

        // 类型索引
        int typeNum = 0;
        // 保存此群体的手机号
        HashSet<String> groupUserPhoneNum = new HashSet<>();
        // -------------- 4、添加每个群体的节点        ---------------------
        for (String groupId : groupIds) {
            if (Objects.equals(groupId, "")) {
                continue;
            }
            GroupInfoEntity groupInfoEntity = groupInfoDao.selectById(groupId);
            System.out.println(groupInfoEntity);
            if (groupInfoEntity == null) {
                continue;
            }
            // 保存查询到的群体信息
            userGroupVo.getData().add(groupInfoEntity);
            // 保存群类型
            String groupName = groupInfoEntity.getGroupType() + "群 " + groupInfoEntity.getId();
            HashMap<String, String> map = new HashMap<>(1);
            map.put("name", groupName);
            nodesAndLinksBo.getCategories().add(map);

            // 根据用户id查询用户信息
            String[] userIds = groupInfoEntity.getGroupUserid().split(",");
            for (String userId : userIds) {
                UserInfoEntity groupUserInfoEntity = userGroupDao.selectById(userId);
                if (groupUserInfoEntity == null) {
                    continue;
                }
                // 查询到当前用户，直接跳过
                if (groupUserInfoEntity.getPhoneNum().equals(userInfoEntity.getPhoneNum())) {
                    continue;
                }
                // 将该节点插入
                NodeBo nodeBo = NodeBo.builder().name(groupUserInfoEntity.getPhoneNum()).value(String.valueOf(groupUserInfoEntity.getInfluence()))
                        .category(typeNum).attr(groupUserInfoEntity).build();
                nodes.add(nodeBo);
                groupUserPhoneNum.add(groupUserInfoEntity.getPhoneNum());

            }
            // 添加一个类型，类型索引加1
            typeNum += 1;

        }

        // -------------- 5、添加边        ---------------------

        for (String groupUserPhone : groupUserPhoneNum) {

            // 当前用户与他人关系
            Integer count = userRelationDao.selectCount(new QueryWrapper<UserRelationEntity>().eq("phone_num1", userInfoEntity.getPhoneNum()).eq("phone_num2", groupUserPhone));
            if (count != 0) {
                LinkBo linkBo = LinkBo.builder().source(userInfoEntity.getPhoneNum()).target(groupUserPhone).build();
                links.add(linkBo);
            }
            // 其他用户之间的关系
            for (String s : groupUserPhoneNum) {
                Integer count1 = userRelationDao.selectCount(new QueryWrapper<UserRelationEntity>().eq("phone_num1", groupUserPhone).eq("phone_num2", s));
                if (count1 == 0) {
                    continue;
                }

                LinkBo linkBo1 = LinkBo.builder().source(groupUserPhone).target(s).build();
                links.add(linkBo1);

            }


        }
        nodesAndLinksBo.setNodes(nodes);
        nodesAndLinksBo.setLinks(links);
        userGroupVo.setStatus(1);
        userGroupVo.setNodesAndLinks(nodesAndLinksBo);

        return ResponseDTO.succData(userGroupVo);
    }

    /**
     * 获取用户常用联系人
     *
     * @param phoneNum 手机号
     * @return 返回常用联系人
     */
    @Override
    public ResponseDTO<KeyPersonInfoVo> getKeyPersonInfo(String phoneNum) {

        KeyPersonInfoVo keyPersonInfoVo = new KeyPersonInfoVo();

        UserInfoEntity userInfoEntity = userGroupDao.selectOne(new QueryWrapper<UserInfoEntity>().eq("phone_num", phoneNum));

        if (null == userInfoEntity) {
            return ResponseDTO.wrap(GroupResponseCodeConst.PHONE_NOT_EXISTS);
        }

        keyPersonInfoVo.setThisUserInfo(userInfoEntity);

        //获取常联系人
        List<FrequentContactBo> frequentContacts = new ArrayList<>();

        List<UserRelationEntity> userRelationEntities = userRelationDao.listFrequentContacts(phoneNum, 5);

        for (UserRelationEntity userRelationEntity : userRelationEntities) {
            if (phoneNum.equals(userRelationEntity.getPhoneNum1())) {
                frequentContacts.add(new FrequentContactBo(userRelationEntity.getPhoneNum2(), userRelationEntity.getRelation()));
            } else {
                frequentContacts.add(new FrequentContactBo(userRelationEntity.getPhoneNum1(), userRelationEntity.getRelation()));
            }
        }
        keyPersonInfoVo.setFrequentContacts(frequentContacts);

        return ResponseDTO.succData(keyPersonInfoVo);
    }

    /**
     * 通过群体id获取群体信息
     *
     * @param groupId 群体id
     * @return 返回群体信息
     */
    @Override
    public ResponseDTO<GroupInfoVo> getGroup(String groupId) {

        GroupInfoVo groupInfoVo = new GroupInfoVo();
        HashMap<String, Integer> idInfo = new HashMap<>();


        // 查找属于群体的用户
        List<UserInfoEntity> userInfoEntities = userGroupDao.listGroupUserInfos(groupId);


        int isSensitiveNum = 0;
        int isNotSensitiveNum = 0;

        ArrayList<String> userLabelList = new ArrayList<>();
        ArrayList<String> cityList = new ArrayList<>();
        for (UserInfoEntity userInfoEntity : userInfoEntities) {
            // 统计敏感用户
            String isSensitiveUser = userInfoEntity.getIsSensitiveUser();
            if ("Y".equals(isSensitiveUser)) {
                isSensitiveNum += 1;
            } else {
                isNotSensitiveNum += 1;
            }
            userLabelList.add(userInfoEntity.getUserLabel());
            cityList.add(userInfoEntity.getCity());
        }
        idInfo.put("isSensitiveNum", isSensitiveNum);
        idInfo.put("isNotSensitiveNum", isNotSensitiveNum);
        groupInfoVo.setIdInfo(idInfo);

        Map<String, Integer> userLabelMap = CollectionUtil.frequencyOfListElements(userLabelList);
        groupInfoVo.setUserLabelInfo((HashMap<String, Integer>) userLabelMap);

        // 获取地区的省份并统计
        ArrayList<String> provinceList = new ArrayList<>();
        for (String city : cityList) {
            List<RegionEntity> regionEntityList = regionDao.selectList(new QueryWrapper<RegionEntity>().eq("name", city));
            if (null == regionEntityList || regionEntityList.isEmpty()) {
                provinceList.add("未知");
                continue;
            }
            Integer parentCode = regionEntityList.get(0).getParentCode();
            if (parentCode == 0) {
                // 省，直接添加
                provinceList.add(regionEntityList.get(0).getName());
            } else {
                // 市，需要查找其省份
                RegionEntity provinceEntity = regionDao.selectById(parentCode);
                if (null == provinceEntity) {
                    provinceList.add("未知");
                } else {
                    provinceList.add(provinceEntity.getName());
                }
            }
        }

        Map<String, Integer> cityMap = CollectionUtil.frequencyOfListElements(provinceList);
        groupInfoVo.setCityInfo((HashMap<String, Integer>) cityMap);

        return ResponseDTO.succData(groupInfoVo);
    }

    /**
     * 通过关键词获取群体信息
     *
     * @param groupKeyword 群体关键词
     * @return 群体信息
     */
    @Override
    public ResponseDTO<List<GroupVo>> getGroupInfo(String groupKeyword) {


        List<GroupVo> groupInfoEntityList = groupInfoDao.listGroupInfos(groupKeyword);
        for (GroupVo groupVo : groupInfoEntityList) {

            String[] groupKeywordSplit = groupVo.getGroupKeyword().split(",");
            for (int i = 0; i < groupKeywordSplit.length; i++) {
                log.info(groupKeyword);
                log.info(groupKeywordSplit[i]);

                if (groupKeywordSplit[i].contains(groupKeyword)) {
                    ArrayList<Integer> objects = new ArrayList<>();
                    objects.add(i);
                    groupVo.setKeywordLocal(objects);
                }
            }
        }

        return ResponseDTO.succData(groupInfoEntityList);
    }

}
